

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>

#include <vector.h>
#include <local.h>


arg_struct args;

int parse_args(int, char **);
int parse_r_theta_vect(char *);
int parse_vect(char *);
void load_vects_from_file(char *);
void run_operations(unsigned int, vm_vector *, int);

int main(int argc, char **argv){

  int ok = parse_args(argc, argv);
  if (!ok){
    printf("Error parsing args; exiting.\n");
    exit(1);
  }

#ifdef _DEBUG
  printf("Vectors:\n");
  int i = 0;
  for ( ; i < args.vect_count; i++){
    vm_println(args.vect_array[i]);
  }
  printf("Operation flags: 0x%08x\n", args.flags);
#endif

  run_operations(args.flags, args.vect_array, args.vect_count);
  
  return 0;

}

int parse_args(int argc, char **argv){

  int i = 1;
  for ( ; i < argc; i++){
    if (argv[i][0] != '-'){
      printf("Invalid argument: %s\n", argv[i]);
      return 0;
    }
    int ok;
    switch (argv[i][1]){
      case 'v':
	ok = parse_vect(argv[++i]);
	if (!ok){
	  printf("Error parsing vector: %s\n", argv[i]);
	  return 0;
	}
	break;
      case 'V': // load vector from (r,theta).
	ok = parse_r_theta_vect(argv[++i]);
	if (!ok){
	  printf("Error parsing (r,theta) vector: %s\n", argv[i]);
	  return 0;
	}
	break;
      case 'f': // A file to find vectors in
	load_vects_from_file(argv[++i]);
	break;
      case 'a': // OP: Add the vectors
	args.flags |= FLAG_OP_ADD;
	break;
      case 's': // OP: Subtract the vectors
	args.flags |= FLAG_OP_SUB;
	break;
      case 'c': // OP: cross the vectors
	args.flags |= FLAG_OP_CROSS;
	break;
      case 'd': // OP: dot the vectors
	args.flags |= FLAG_OP_DOT;
	break;
      case 'i': // OP: inverse the vectors
	args.flags |= FLAG_OP_INV;
	break;
      case 'm': // OP: take the magnitude of the vectors
	args.flags |= FLAG_OP_MAG;
	break;
      case 'n': // OP: norm the vectors
	args.flags |= FLAG_OP_NORM;
	break;
      case 'p': // OP: project the vectors
	args.flags |= FLAG_OP_PROJECT;
	break;
      case 'A': // OP: angle between the vectors
	args.flags |= FLAG_OP_ANGLE;
	break;
      case 'P': // OP: print all vects (this makes r_thetas into components)
	args.flags |= FLAG_OP_PRINT;
	break;
      case 'h': // Help options
	args.flags |= FLAG_HELP;
	break;
      default:
	printf("Invalid option: %s\n", argv[i]);
	return 0;
    }
  }
  return 1;

}

int parse_r_theta_vect(char *vect){

  int use_degrees = 0;

  /* First find the vector in component form. */
  double theta, r;

  int conv = sscanf(vect, "[%lf:d%lf]", &r, &theta);
  if (conv == 2) {
    use_degrees = 1;    
  } else {
    conv = sscanf(vect, "[%lf:%lf]", &r, &theta);
  }

  if (use_degrees){
    /* Convert to radians then proceed. */
    theta = theta * (M_PI / 180);
  }

  vm_vector v;
  v.x = r * cos(theta);  
  v.y = r * sin(theta);
  v.z = 0;
  v.w = 0;

  vm_vector *new_vect_array = 
    (vm_vector *) malloc(sizeof(vm_vector) * (args.vect_count + 1));
  memmove(new_vect_array, args.vect_array, 
	  args.vect_count * sizeof(vm_vector));
  new_vect_array[args.vect_count++] = v;
  free(args.vect_array);
  args.vect_array = new_vect_array;

  return 1;

}



int parse_vect(char *vect){

  vm_vector v;
  int ok = vm_sread(vect, &v);
  if (!ok){
    return 0;
  }
  
#ifdef _DEBUG
  printf("Vector Array Current Len=%db  New Len=%db\n",
	 (int) sizeof(vm_vector) * args.vect_count,
	 (int) sizeof(vm_vector) * (args.vect_count + 1));
#endif

  vm_vector *new_vect_array = 
    (vm_vector *) malloc(sizeof(vm_vector) * (args.vect_count + 1));
  memmove(new_vect_array, args.vect_array, 
	  args.vect_count * sizeof(vm_vector));
  new_vect_array[args.vect_count++] = v;
  free(args.vect_array);
  args.vect_array = new_vect_array;
  return 1;

}

void load_vects_from_file(char *file){

#ifdef _DEBUG
  printf("Attempting to read vectors from file: %s\n", file);
#endif

  FILE *vect_f = fopen(file, "r");
  if (!vect_f){
    perror("Could not open vector file");
    exit(1);
  }

  vm_vector tmp;
  while (vm_read(vect_f, &tmp)){
#ifdef _DEBUG
    printf("Vector Array Current Len=%db  New Len=%db\n",
	   (int) sizeof(vm_vector) * args.vect_count,
	   (int) sizeof(vm_vector) * (args.vect_count + 1));
#endif

    vm_vector *new_vect_array = 
      (vm_vector *) malloc(sizeof(vm_vector) * (args.vect_count + 1));
    memmove(new_vect_array, args.vect_array, 
	    args.vect_count * sizeof(vm_vector));
    new_vect_array[args.vect_count++] = tmp;
    free(args.vect_array);
    args.vect_array = new_vect_array;
  }

}
